package com.zn.socket;

import com.zn.service.OptionTradeService;
import com.zn.util.Constant;
import com.zn.util.LocalInetAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;

/**
 * Created by yinjiawei on 2018/7/21.
 */
@Component
public class ForwardingSocketMsg {
    private static final Logger LOGGER = LoggerFactory.getLogger(ForwardingSocketMsg.class);
    @Autowired
    private OptionTradeService optionTradeService;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    private static ForwardingSocketMsg forwardingSocketMsg;


    @PostConstruct
    public void init() {
        forwardingSocketMsg = this;
    }

    /**
     * 接受来自C++的委托单回报
     * @param msg
     */
    @Async("executorPool")
    public void receiverReportOrderMsg(String msg){
        try{
            //交易日|报单提交状态|报单状态|报单编号|报单来源|报单类型|数量|最小成交量|今成交数量|报单价格|本地报单编号|合约|状态信息|报单时间|错误ID|主机来源
            String [] respReportData=msg.split("\\|");
            String orderRef=respReportData[11];
            String redisReqAddress=forwardingSocketMsg.redisTemplate.opsForValue().get(Constant.ORDER_REF+orderRef);
            LOGGER.info("委托回报redisIp:"+redisReqAddress+",loclIp:"+LocalInetAddress.getLocalAddress());
            if(LocalInetAddress.getLocalAddress().equals(redisReqAddress)){
                //处理委托
                LOGGER.info("本地报单引用为："+orderRef+"进入了此台服务器");
                forwardingSocketMsg.optionTradeService.respReportOrder(msg);
            }
        }catch (Exception e){
            e.printStackTrace();
            LOGGER.error("本地报单编号为："+msg+"在报单回报出异常了",e);
        }

    }

    /**
     * 接受来自C++的成交单回报
     * @param msg
     */
    @Async("executorPool")
    public void receiverDealOrderMsg(String msg){
        try{
            //deal|开平方向|本地报单编号|合约code|报单编号|成交编号|成交日期|成交时间|手数|价格|买卖类型|交易类型|ip
            String [] respDealData=msg.split("\\|");
            String orderRef=respDealData[2];
            String redisReqAddress=forwardingSocketMsg.redisTemplate.opsForValue().get(Constant.ORDER_REF + orderRef);
            LOGGER.info("交单回报redisIp:"+redisReqAddress+",loclIp:"+LocalInetAddress.getLocalAddress());
            if (LocalInetAddress.getLocalAddress().equals(redisReqAddress)) {
                LOGGER.info("成交orderRef为：" + orderRef + "获锁成功");
                forwardingSocketMsg.optionTradeService.respDealOrder(msg);
            } else {
                LOGGER.info("成交orderRef为：" + orderRef + "未在此台机器获取到锁");
            }
        }catch (Exception e){
            LOGGER.error("本地报单编号为："+msg+"在成交回报出异常了",e);
        }

    }

    /**
     * 接受来自C++的风控单
     * @param msg
     */
    /*@Async("executorPool")
    public void receiverRiskOrderMsg(String msg){
        try{
            //riskCloseOrder|合约code|客户子账户|手数|平仓价格|多空方向|开平标识|开仓报单引用
            String [] respDealData=msg.split("\\|");
            String title=respDealData[0],openOrderRef=respDealData[7];
            String lockKey=title+":"+openOrderRef;
            //分布式锁解决多台机器同时接受c++风控单
            boolean lock = forwardingSocketMsg.redisTemplate.opsForValue().setIfAbsent(lockKey, "lock");
            if(lock){
                LOGGER.info("风控单openOrderRef为："+openOrderRef+"获锁成功");
                //设置60s失效时间
                forwardingSocketMsg.redisTemplate.expire(lockKey, 60, TimeUnit.SECONDS);
                forwardingSocketMsg.optionTradeService.respRiskCloseOrder(msg);
                //释放锁
                forwardingSocketMsg.redisTemplate.delete(lockKey);
            }else{
                LOGGER.info("风控单openOrderRef为：：" + openOrderRef+"未在此台机器获取到锁");
            }
        }catch (Exception e){
            e.printStackTrace();
            LOGGER.error("风控单："+msg+"在平仓中出现异常",e);
        }

    }*/

    /**
     * 接受来自C++的提供数据指令（客户持仓单和合约涨跌幅）
     */
   @Async("executorPool")
    public void receiverSendDataFlag(String msg){
        try{
            //tradeStartUp|yyyy-MM-dd HH:mm:ss
            String [] respDealData=msg.split("\\|");
            String titleName=respDealData[0],time=respDealData[1];
            String lockKey=titleName+":"+time;
            //分布式锁解决多台机器同时接受c++风控单
            boolean lock = forwardingSocketMsg.redisTemplate.opsForValue().setIfAbsent(lockKey, "lock");
            if(lock){
                LOGGER.info(LocalInetAddress.getLocalAddress()+"receiverSendDataFlag...msg:"+msg);
                forwardingSocketMsg.redisTemplate.expire(lockKey, 60, TimeUnit.SECONDS);
                forwardingSocketMsg.optionTradeService.sendPositionOrder();
                //释放锁
                forwardingSocketMsg.redisTemplate.delete(lockKey);
            }else{
                LOGGER.info(LocalInetAddress.getLocalAddress()+"receiverSendDataFlag...msg 没获取到锁");
            }
        }catch (Exception e){
            e.printStackTrace();
            LOGGER.error("提供数据指令出现异常",e);
        }
    }
    /**
     * 接受来自C++的提供数据指令（母账户信息）
     */
    /*@Async("executorPool")
    public void giveMeAccount(String msg){
        try{
            //giveMeAccount|yyyy-MM-dd HH:mm:ss
            String [] respDealData=msg.split("\\|");
            String titleName=respDealData[0],time=respDealData[1];
            String lockKey=titleName+":"+time;
            //分布式锁解决多台机器同时接受c++风控单
            boolean lock = forwardingSocketMsg.redisTemplate.opsForValue().setIfAbsent(lockKey, "lock");
            if(lock){
                LOGGER.info(LocalInetAddress.getLocalAddress()+"giveMeAccount...msg:"+msg);
                forwardingSocketMsg.redisTemplate.expire(lockKey, 60, TimeUnit.SECONDS);
                forwardingSocketMsg.futuresTradeService.sendFutureAccountInfo();
                //释放锁
                forwardingSocketMsg.redisTemplate.delete(lockKey);
            }else{
                LOGGER.info(LocalInetAddress.getLocalAddress()+"giveMeAccount...msg 没获取到锁");
            }
        }catch (Exception e){
            e.printStackTrace();
            LOGGER.error("提供数据指令出现异常",e);
        }
    }*/

    /**
     * 处理报单引用校验的结果
     * @param msg
     */
    /*@Async("executorPool")
    public void checkOrderRefResult(String msg){
        try{
            //checkOrderRefResult|orderRef|result(0(报单成功)/1(报单失败)))
            String [] respDealData=msg.split("\\|");
            String titleName=respDealData[0],orderRef=respDealData[1],result=respDealData[2];
            String lockKey=titleName+":"+orderRef;
            //分布式锁解决多台机器同时接受c++风控单
            boolean lock = forwardingSocketMsg.redisTemplate.opsForValue().setIfAbsent(lockKey, "lock");
            if(lock){
                LOGGER.info(LocalInetAddress.getLocalAddress() + "checkOrderRefResult...msg:" + msg);
                forwardingSocketMsg.redisTemplate.expire(lockKey, 60, TimeUnit.SECONDS);
                forwardingSocketMsg.futuresTradeService.orderRefResultHandle(orderRef,result);
                //释放锁
                forwardingSocketMsg.redisTemplate.delete(lockKey);
            }else{
                LOGGER.info(LocalInetAddress.getLocalAddress()+"receiverSendDataFlag...msg 没获取到锁");
            }
        }catch (Exception e){
            LOGGER.error("处理报单引用校验的结果......",e);
        }
    }*/
}
